package com.jishuo.nontax.bfc.service;

import com.github.pagehelper.PageHelper;
import com.jishuo.base.bean.BaseResult;
import com.jishuo.base.bean.ErrorCodeEnum;
import com.jishuo.base.bean.Pagination;
import com.jishuo.base.config.NonTaxConfig;
import com.jishuo.base.service.SequenceService;
import com.jishuo.base.util.CommonUtil;
import com.jishuo.base.util.ExportSXSSFUtil;
import com.jishuo.base.util.StringUtil;
import com.jishuo.nontax.bean.bank.OnlineOrder;
import com.jishuo.nontax.bean.bank.PaySpecial;
import com.jishuo.nontax.bean.message.SetBankPaySpecialBackOut;
import com.jishuo.nontax.bean.message.SetPaySpecial;
import com.jishuo.nontax.bean.message.SetPaySpecialNew;
import com.jishuo.nontax.bean.vo.PaySpecialVO;
import com.jishuo.nontax.bfc.dao.SpecialMapper;
import com.jishuo.nontax.bfc.pzk.PzkService;
import com.jishuo.nontax.bfc.tlq.MessageFactory;
import com.jishuo.nontax.bfc.tlq.MessageService;
import com.jishuo.nontax.util.BillStateUtil;
import com.jishuo.nontax.util.PzkUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author :hanlipeng
 * @description :
 * @create :2022-12-22 10:51:00
 */
@Service
public class SpecialService {

    private static Logger logger = LoggerFactory.getLogger(SpecialService.class);

    @Resource
    private SpecialMapper specialMapper;
    @Resource
    private SequenceService sequenceService;
    @Resource
    private MessageService messageService;
    @Resource
    private NonTaxConfig nonTaxConfig;
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Resource
    private OnlineOrderService onlineOrderService;
    @Resource
    private PzkService pzkService;
    @Resource
    private PzkUtils pzkUtils;

    /**
     * 划解专户收款
     *
     * @param billnum     票号
     * @param bankaffirm  交易流水号
     * @param paybankdt   交易时间
     * @param bankstation 网点
     * @return
     */
    public BaseResult setSpecialPayInfo(String billnum, String bankaffirm, String paybankdt, String bankstation, String paychnl) {
        // 参数检查
        String retMsg = "";
        if (billnum == null || "".equals(billnum)) {
            retMsg += "票号未填写；";
        } else if (paybankdt == null || "".equals(paybankdt)) {
            retMsg += "缴费时间未填写；";
        } else if (bankaffirm == null || "".equals(bankaffirm)) {
            retMsg += "交易流水号未填写；";
        }
        if (!"".equals(retMsg)) {
            logger.info("缴费参数错误。" + retMsg);
            return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        }
        //根据单号查询化解专户
        PaySpecialVO specialInfo = specialMapper.findPaySpecial(billnum);
        if (specialInfo == null) {
            return new BaseResult(ErrorCodeEnum.BILL_NOT_FOUND);
        }
        // 判断是否已缴费
        if (specialInfo.getIsbankaffirm() == 1) {
            // 日期一致的允许二次提交
            if (!paybankdt.substring(0, 10).equals(specialInfo.getPaybankdt().substring(0, 10)))
                return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        } else if (specialInfo.getBillstate() == 3) {
            return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        }
        try {
            // 更新业务表
            specialInfo.setBankaffirm(bankaffirm);
            specialInfo.setPaybankdt(paybankdt);
            specialInfo.setBankstation(bankstation);
            specialInfo.setSendtime(sdf.format(new Date()));
            specialInfo.setIsbankaffirm(1);
            specialInfo.setHxbankaffirm(bankaffirm);
            int i = specialMapper.updateSpecialBankAffirm(specialInfo);
            if (i < 1) {
                return new BaseResult(ErrorCodeEnum.DB_ERR.getCode(), "更新化解专户失败（" + billnum + "）");
            }

            OnlineOrder oo = new OnlineOrder();
            oo.setBillnum(specialInfo.getBillnum());
            oo.setAmt(specialInfo.getItemmoney1().toPlainString());
            oo.setBankaffirm(specialInfo.getBankaffirm());
            oo.setBilltype(9);
            oo.setPaybankdt(specialInfo.getPaybankdt());
            oo.setPaychnl(paychnl);
            oo.setPayee(specialInfo.getPayeebankname());
            oo.setPayeeaccount(specialInfo.getPayeebankaccount());
            oo.setPayer(specialInfo.getAccountname());
            oo.setPayeraccount(specialInfo.getAccountcode());
            oo.setPaytype(2);
            onlineOrderService.saveOnlineOrder(oo);

            // 发送财政
            Object obj = MessageFactory.setSpecialPayInfo(specialInfo);
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            messageService.sendMessage("SETBANKPAYSPECIAL", messageid, obj, "2.0");

            // 写凭证
            pzkService.savePzmsg("SETSPECIALPZK", pzkUtils.getSpecial(specialInfo));
        } catch (Exception e) {
            logger.info("划解专户失败：" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.TLQ_ERR);
        }

        return new BaseResult();
    }

    /**
     * 财政返回票据，入库
     * @param data 财政报文
     * @param billstate 票据状态
     * @param sn 消息sn
     */
    public void setPaySpecial(String data, int billstate, String sn) {
        if (billstate == 1) {
            try {
                Serializer serializer = new Persister();
                SetPaySpecial setPaySpecial = serializer.read(SetPaySpecial.class, new StringReader(data));
                // 对象赋值
                PaySpecialVO vo = new PaySpecialVO(setPaySpecial);
                vo.setBillstate(billstate);
                vo.setIssend(2);
                specialMapper.updatePaySpecial(vo);
            } catch (Exception e) {
                logger.info("处理获取划解专户失败：" + e.toString(), e);
            }
        } else if (billstate > 1) {
            long messageid = Long.parseLong(sn.substring(sn.indexOf("-") + 1));
            specialMapper.updateBillState(messageid, billstate);
        }
    }

    /** 财政返回票据，入库 v2.4 */
    public void setPaySpecialNew(String data, int billstate, String sn) {
        //xml解析器
        Serializer serializer = new Persister();
        try {
            //正常
            if (billstate == 1) {
                SetPaySpecialNew special = serializer.read(SetPaySpecialNew.class, new StringReader(data));
                // 对象赋值
                PaySpecialVO vo = new PaySpecialVO(special);
                vo.setBillstate(billstate);
                vo.setIssend(2);
                specialMapper.updatePaySpecial(vo);
            } else if (billstate > 1) {
                long messageid = Long.parseLong(sn.substring(sn.indexOf("-") + 1));
                specialMapper.updateBillState(messageid, billstate);
            }
        } catch (Exception e) {
            logger.info("处理获取划解专户失败：" + e.toString(), e);
        }
    }


    public int updateSpecial(PaySpecialVO special) {
        int i = specialMapper.findSpecialCount(special.getBillnum());
        if (i > 0) {
            special.setIssend(2);
            special.setBillstate(1);
            special.setIsbankaffirm(1);
            return specialMapper.updateSpecial(special);
        } else {
            special.setIssend(2);
            special.setBillstate(1);
            return specialMapper.insertSpecial(special);
        }
    }

    /**
     * @param billnum 票据号
     * @auther dinggaofei
     * @Date 2022/12/27  13:50
     * @description 记录划解专户票据号，并向财政获取划解专户单据信息
     */
    public BaseResult getPaySpecial(String billnum) {
        //根据票号从本地获取化解专户
        PaySpecialVO spe = specialMapper.findSpecialInfo(billnum);
        //xml解析器
        Serializer serializer = new Persister();
        //xml转换器
        StringWriter sw = new StringWriter();
        try {
            BaseResult result = new BaseResult();
            //已缴费的直接返回
            if (spe != null && (spe.getBillstate() == 3 || spe.getIsbankaffirm() == 1)) {
                spe.setBillstate(3);
                serializer.write(spe, sw);
                result.setData(sw.toString());
                return result;
            }
            // 更新messageid
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            if (spe == null) {
                long payid = sequenceService.getNextSeq("FSPAYSPECIALSEQ");
                spe = new PaySpecialVO();
                spe.setPayid(payid);
                spe.setBillnum(billnum);
                spe.setMessageid(messageid);
                specialMapper.insertSpecial(spe);
            } else {
                spe.setMessageid(messageid);
                specialMapper.updateSpecial(spe);
            }
            // 从财政查询
            boolean suc = messageService.sendAndRecvMessage("GETPAYSPECIAL", messageid, MessageFactory.getPaySpecial(billnum), "2.4");

            if (suc) {
                spe = specialMapper.findSpecialInfo(billnum);
                PaySpecial paySpecial = spe.getPaySpecial();
                serializer.write(paySpecial, sw);
                result.setData(sw.toString());
                return result;
            }
            return new BaseResult(ErrorCodeEnum.BILL_GET_TIMEOUT);
        } catch (Exception e) {
            logger.info("失败：" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.SYS_ERR);
        }
    }

    /**
     * 化解专户列表
     *
     * @param paySpecialVO
     * @param pagination
     * @return
     */

    public List<PaySpecialVO> listSpecial(PaySpecialVO paySpecialVO, Pagination pagination) {
        if (pagination.getRows() > 0) PageHelper.startPage(pagination.getPage(), pagination.getRows());
        return this.specialMapper.findSpecialPage(paySpecialVO);
    }

    public BaseResult saveSpecial(PaySpecialVO paySpecialVO) {
        int n = specialMapper.saveSpecial(paySpecialVO);
        if (n < 1) return new BaseResult(ErrorCodeEnum.DB_ERR);
        return new BaseResult();
    }

    public PaySpecialVO getSpecial(Long billid) {
        PaySpecialVO paySpecialVO = specialMapper.getSpecial(billid);
        return paySpecialVO;
    }

    public BaseResult sendSpecial(String billnum, PaySpecialVO vo) {
        if (vo == null) vo = specialMapper.findSpecialInfo(billnum);
        if (vo.getIsbankaffirm() == 0) return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), "不允许发送未缴费单据");

        // 发送财政
        try {
            Object obj = MessageFactory.setSpecialPayInfo(vo);
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            messageService.sendMessage("SETBANKPAYSPECIAL", messageid, obj, "2.0");
            return new BaseResult();
        } catch (Exception e) {
            logger.info("发送财政失败。" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.TLQ_ERR);
        }
    }

    /**
     * 发送化解专户
     *
     * @param billids  流水号
     * @return
     */
    public BaseResult sendSpecial(String billids) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<PaySpecialVO> vos = specialMapper.findSpecial(ids);

        for (PaySpecialVO vo:vos) {
            sendSpecial(vo.getBillnum(), vo);
        }
        return new BaseResult();
    }

    /**
     * 冲销划解专户信息
     *
     * @param billids   流水号
     * @param usercode 用户密码
     * @return
     */
    public BaseResult cleanSpecial(String billids, String usercode) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<PaySpecialVO> list = specialMapper.findSpecial(ids);

        Calendar cal = Calendar.getInstance();
        String cxTime = sdf.format(cal.getTime());
        cal.add(Calendar.MINUTE, 0 - nonTaxConfig.CxTime);
        String chkTime = sdf.format(cal.getTime());

        String errinfo = "";
        for (PaySpecialVO vos : list) {
            if (StringUtil.isEmpty(vos.getSendtime()) || chkTime.compareTo(vos.getSendtime()) < 0) {
                setSpecialBackOut(cxTime, usercode, vos);
            } else {
                errinfo += vos.getBillnum() + ",";
            }
        }
        if (!errinfo.equals("")) {
            errinfo += "超时冲销失败,其他单据冲销成功!";
            return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), errinfo);
        } else {
            errinfo = "冲销成功";
            return new BaseResult(ErrorCodeEnum.SUCCESS.getCode(), errinfo);
        }
    }

    private BaseResult setSpecialBackOut(String backoutdt, String backoutname, PaySpecialVO vo) {
        try {
            SetBankPaySpecialBackOut out = new SetBankPaySpecialBackOut();
            out.setBackoutname(backoutname);
            out.setBankaffirm(vo.getBankaffirm());
            out.setBankstation(vo.getBankstation());
            out.setBillnum(vo.getBillnum());
            out.setCantonid(StringUtil.toStr(vo.getCantonid()));
            out.setItemid(StringUtil.toStr(vo.getItemid1()));
            out.setMoney(vo.getItemmoney1().toPlainString());
            out.setPaybankdt(vo.getPaybankdt());
            out.setPayeeaccount(vo.getPayeebankaccount());
            out.setPayeebankname(vo.getPayeebankname());
            out.setPaybankdt(vo.getPaybankdt());
            out.setPayeelevel(StringUtil.toStr(vo.getPayeelevel()));
            out.setPayeeunitname(vo.getPayeeunitname());
            out.setPayerbankid(StringUtil.toStr(vo.getPayerbankid()));
            out.setPayid(StringUtil.toStr(vo.getPayid()));
            out.setRemark("冲销");

            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");

            //发送到财政
            messageService.sendMessage("SETBANKPAYSPECIALBACKOUT", messageid, out, "2.0");
            specialMapper.updateIsBankAffirm(vo.getPayid());

            // 写凭证
            pzkService.savePzmsgOut(BillStateUtil.BillType_SpecialPay, vo.getBillnum(), vo.getBankaffirm());

            return new BaseResult();
        } catch (Exception e) {
            logger.info("专户冲销失败：" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
        }
    }


    public void specialExport(long bankid, String paybankdt, HttpServletResponse response) {
        if (bankid == 0 || StringUtil.isEmpty(paybankdt)) return;
        PaySpecialVO vo = new PaySpecialVO();
        vo.setPayerbankid(bankid);
        vo.setPaybankdt(paybankdt);
        List<PaySpecialVO> specialPage = specialMapper.findSpecialPage(vo);
        String[] headers = {"流水号", "票据号", "区划id", "区划编码", "区划名称", "缴款开户银行流水号", "银行名称", "账户名称", "账号", "预算级次", "收款单位名称", "收款单位银行名称", "收款单位银行账号", "项目流水号", "项目编码", "项目名称", "项目金额", "银行划款时间", "银行网点名称", "银行交易流水号", "单据状态", "发送时间", "__status", "银行核心交易流水号", "是否发送"};
        String[] col = {"payid", "billnum", "cantonid", "cantoncode", "cantonname", "payerbankid", "payerbankname", "payeraccountname", "payeraccountcode", "payeelevel", "payeeunitname", "payeebankname", "payeebankaccount", "itemid1", "itemcode", "itemname", "itemmoney1", "paybankdt", "bankstation", "bankaffirm", "billstate", "sendtime", "", "hxbankaffirm", "issend"};
        ExportSXSSFUtil ex = new ExportSXSSFUtil();
        SXSSFWorkbook workbook = ex.exportExcelSXSSF("化解专户列表", headers, col, specialPage, null);
        response.setContentType("application/vnd.ms-excel");
        try {
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    new String(("化解专户.xls").getBytes(), "iso-8859-1"));
            OutputStream ouputStream = response.getOutputStream();
            workbook.write(ouputStream);
            ouputStream.flush();
            ouputStream.close();
        } catch (Exception e) {
            logger.info("导出失败：" + e.toString());
        }
    }
}

